package com.encapi.framework.core;

import com.encapi.framework.constant.EncapiConstant;
import com.encapi.framework.exception.DecryptBodyException;
import com.encapi.framework.exception.EncryptBodyException;
import com.encapi.framework.handler.CryptHandler;
import com.encapi.framework.properties.EncapiProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 加解密管理器
 * @author xzbcode
 */
public class CryptManager {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    private static final Map<String, CryptHandler> algIndex = new HashMap<>();

    @Resource
    private EncapiProperties encapiProp;

    @Autowired
    public CryptManager(List<CryptHandler> handlers) {
        // 注入处理器
        for (CryptHandler handler : handlers) {
            algIndex.put(handler.getAlgorithm(), handler);
        }
    }

    @PostConstruct
    public void initInfo() {
        if (log.isInfoEnabled()) {
            log.info("[encapi] crypt manager init successfully, current algorithm is '{}'.", getAlgorithm());
        }
    }

    /**
     * 加密
     * @param headers 请求头
     * @param plainText 明文
     * @return String
     * @throws EncryptBodyException 加密失败异常
     */
    public String encrypt(String plainText, HttpServletRequest request, HttpHeaders headers) throws EncryptBodyException {
        return this.getHandlerByAlg(this.getAlgorithm()).encrypt(plainText, request, headers);
    }

    /**
     * 解密
     * @param headers 请求头
     * @param cipherText 密文
     * @return String
     * @throws DecryptBodyException 解密失败异常
     */
    public String decrypt(String cipherText, HttpServletRequest request, HttpHeaders headers) throws DecryptBodyException {
        return this.getHandlerByAlg(this.getAlgorithm()).decrypt(cipherText, request, headers);
    }

    /**
     * 获取配置的加解密器类型
     * @return
     */
    private String getAlgorithm() {
        String alg = encapiProp.getAlg();
        if (alg == null) {
            alg = EncapiConstant.ALG_AES;
        }
        return alg;
    }


    /**
     * 获取对应算法的处理器
     * @param alg 处理器类型
     * @return
     */
    private CryptHandler getHandlerByAlg(String alg) {
        CryptHandler cryptHandler = algIndex.get(alg);
        if (cryptHandler == null) {
            throw new IllegalStateException("crypt handler not yet registered.");
        }
        if (log.isDebugEnabled()) {
            log.debug("[encapi] current crypt handler is {}", cryptHandler.getClass().getSimpleName());
        }
        return cryptHandler;
    }

}
